package com.accounting.client.frontend.product.handlers;

import java.util.Date;
import java.util.List;

import com.accounting.client.ApplicationContext;
import com.accounting.client.frontend.common.MoneyField;
import com.accounting.client.frontend.packages.PackageRow;
import com.accounting.client.remote.Services;
import com.accounting.client.remote.enumeration.Currency;
import com.accounting.client.remote.enumeration.PackageType;
import com.accounting.client.remote.enumeration.StockLocation;
import com.accounting.client.remote.obj.PackageItem;
import com.accounting.client.remote.obj.PurchaseRecordItem;
import com.accounting.client.remote.obj.User;
import com.accounting.client.remote.transfer.AddPackageRequest;
import com.accounting.client.remote.transfer.CreatePurchaseRecordRequest;
import com.accounting.client.resource.BoxResources;
import com.accounting.client.session.ErrorHandler;
import com.accounting.client.session.Session;
import com.accounting.client.session.SessionManager;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Widget;
import corelib.client.CollectionUtil;
import corelib.client.Util;
import corelib.client.delegate.Action;
import corelib.client.delegate.CompleteCallback;
import corelib.client.delegate.DataCallback;
import corelib.client.delegate.Func1;
import corelib.client.linq.Linq;
import corelib.client.resource.CommonResources;
import corelib.client.ui.LazyWidget;
import corelib.client.ui.SimpleModal;
import corelib.client.ui.widget.Size;
import corelib.client.ui.widget.WidgetListener;
import corelib.client.ui.widget.button.Button;
import corelib.client.ui.widget.form.DateBox;
import corelib.client.ui.widget.form.DecimalBox;
import corelib.client.ui.widget.form.ImageWidget;
import corelib.client.ui.widget.form.IntInputBox;
import corelib.client.ui.widget.form.SelectField;
import corelib.client.ui.widget.form.SimpleLabel;
import corelib.client.ui.widget.form.fomatters.NullableValueFormatter;
import corelib.client.ui.widget.form.fomatters.ValueFormatter;
import corelib.client.ui.widget.layout.LabelAlignment;
import corelib.client.ui.widget.layout.RelativeColumn;
import corelib.client.ui.widget.layout.RelativeLayout;
import corelib.client.ui.widget.layout.RelativeRow;
import corelib.client.ui.widget.messagebox.SimpleMessageBox;

public class CreatePurchaseRecordPanel extends LazyWidget<FlowPanel> {
	
	private final List<PackageRow> packages = CollectionUtil.newArrayList();
	
	private MoneyField costField;
	private MoneyField postageField;
	private IntInputBox countField;
	
	private SelectField<User> buyerField;
	private SelectField<User> posterField;
	private SelectField<StockLocation> locationField;
	private DecimalBox currencyRateField;
	private DateBox datePurchasedField;
	
	private ImageWidget addPackageIcon;
	private PurchaseRecordItem purchaseRecordItem;
	
	private RelativeColumn packageColumn;
	private RelativeColumn buttonGroups;
	
	private Action action;
	
	public CreatePurchaseRecordPanel(PurchaseRecordItem item, Action action){
		this.action = action;
		this.purchaseRecordItem = item;
		this.packageColumn = new RelativeColumn();
		this.buttonGroups  = new RelativeColumn();
		this.packageColumn.setRowSpacing(10);
	}
	
	@Override
	protected FlowPanel createWidget() {
		FlowPanel panel = new FlowPanel();
		panel.getElement().getStyle().setPadding(10, Unit.PX);
		
		RelativeColumn column = new RelativeColumn();
		int lw = 100;
		int fw = 100;
		
		datePurchasedField = new DateBox();
		datePurchasedField.setDate(new Date());
		
		addPackageIcon = new ImageWidget(BoxResources.INSTANCE.plus16(),new Size(16,16),new WidgetListener(){
			@Override
			public void valueUpdated(Widget widget) {
				PackageRow row = new PackageRow(packages);
				packages.add(row);
				packageColumn.addRow(row);
			}
		});
		addPackageIcon.setEnabled(false);
		
		countField = new IntInputBox();
		costField  = new MoneyField(Currency.AUD,    true);
		postageField  = new MoneyField(Currency.AUD, false);
		
		locationField = new SelectField<StockLocation>(StockLocation.All, new WidgetListener(){
			@Override
			public void valueUpdated(Widget widget) {
				if (StockLocation.China == locationField.getSelectedOption()) {
					postageField.setEnable(true);
					addPackageIcon.setEnabled(true);
				}
				else {
					postageField.getValueField().setDouble(null);
					postageField.setEnable(false);
					addPackageIcon.setEnabled(false);
					packageColumn.clear();
				}
			}
		});
		 
		locationField.setNullable(true);
		locationField.setOptionFormatter("请选择库存位置", new ValueFormatter<StockLocation>(){
			@Override
			public String format(StockLocation value) {
				return value.getCname();
			}
		});
		
		buyerField = new SelectField<User>(ApplicationContext.getAllUsers(), new NullableValueFormatter<User>(){
			@Override
			protected String formatNull() {
				return "请选择购买员";
			}
			@Override
			protected String formatNotNull(User value) {
				return value.getCName();
			}
		});
		
		buyerField.setNullable(true);
		buyerField.setSelectedOption(ApplicationContext.getUser(Session.Current.getUserId()));
		
		posterField = new SelectField<User>(ApplicationContext.getAllUsers(), new NullableValueFormatter<User>(){
			@Override
			protected String formatNull() {
				return "请选择邮寄操作员";
			}
			@Override
			protected String formatNotNull(User value) {
				return value.getCName();
			}
		});
		posterField.setNullable(true);
		posterField.setSelectedOption(ApplicationContext.getUser(Session.Current.getUserId()));
		
		currencyRateField = new DecimalBox();
		currencyRateField.setDouble(ApplicationContext.getCurrentRate());
		
		RelativeRow row = column.addRow();
		row.add(new SimpleLabel("").setBold(true),new SimpleLabel(purchaseRecordItem.getProductName()).setBold(true), RelativeLayout.create(200, LabelAlignment.Top, lw));
		row.add(new SimpleLabel("数量").setBold(true),countField, RelativeLayout.create(fw, LabelAlignment.Top, lw));
		row.addSpace(12);
		row.add(new SimpleLabel("单件购买成本").setBold(true), costField.getValueField(), RelativeLayout.create(fw, LabelAlignment.Top, lw));
		row.addSpace(12);
		row.add(new SimpleLabel("购买员").setBold(true),   buyerField, RelativeLayout.create(fw, LabelAlignment.Top, lw));
		row.addSpace(12);
		row.add(new SimpleLabel("库存位置").setBold(true),  locationField, RelativeLayout.create(fw, LabelAlignment.Top, lw));
		row.addSpace(12);
		row.add(new SimpleLabel("单件邮费").setBold(true),  postageField.getValueField(), RelativeLayout.create(fw, LabelAlignment.Top, lw));
		row.addSpace(12);
		row.add(new SimpleLabel("邮寄员").setBold(true),    posterField, RelativeLayout.create(fw, LabelAlignment.Top, lw));
		row.addSpace(12);
		row.add(new SimpleLabel("当前汇率").setBold(true),  currencyRateField, RelativeLayout.create(fw, LabelAlignment.Top, lw));
		row.addSpace(12);
		row.add(new SimpleLabel("购买时间").setBold(true),  datePurchasedField, RelativeLayout.create(fw, LabelAlignment.Top, lw));
		row.addSpace(12);
		row.add(new SimpleLabel(Util.EMPTY_STRING), addPackageIcon, RelativeLayout.create(24, LabelAlignment.Top, 24));
		
		Button submitBtn = new Button("递交新库存", CommonResources.INSTANCE.accept16(), new WidgetListener(){
			@Override
			public void valueUpdated(Widget widget) {
				addNewPurchaseRecord();
			}
		});
		
		Button resetBtn = new Button("重置", CommonResources.INSTANCE.accept16(), new WidgetListener(){
			@Override
			public void valueUpdated(Widget widget) {
				packageColumn.clear();
				packages.clear();
				reset();
			}
		});

		buttonGroups.addRow().addSpace(200).add(submitBtn, 100).addSpace(12).add(resetBtn, 100);
		
		column.setRowSpacing(12);
		column.addRow().add(packageColumn);
		column.addRow().add(buttonGroups);
		panel.add(column.getPanel());
		return panel;
	}
	
	private void reset() {
		datePurchasedField.reset();
		buyerField.setSelectedOption(null);
		countField.setInteger(purchaseRecordItem.getCount());
		costField.getValueField().setDouble(purchaseRecordItem.getCost());
		locationField.setSelectedOption(null);
		postageField.getValueField().setDouble(null);
		currencyRateField.setDouble(ApplicationContext.getCurrentRate());
	}
	
	private void addNewPurchaseRecord() {
		if (countField.getInteger(0) <= 0){
			countField.markError("请输入购买产品数量 (产品数量不能为零)");
			return;
		}
		
		if (costField.getValue() == 0.0){
			costField.getValueField().markError("请输入产品成本 (产品购买单价不能为零).");
			return;
		}
		
		if (buyerField.getSelectedOption() == null){
			buyerField.markError("请选择购买员");
			return;
		}
		
		if (locationField.getSelectedOption() == null) {
			locationField.markError("请选择产品存放位置.");
			return;
		}
		
		if (locationField.getSelectedOption() == StockLocation.China) {
			if (posterField.getSelectedOption() == null){
				posterField.markError("请选择邮寄操作员");
				return;
			}
			
			if (postageField.getValueField().getDouble() == null || postageField.getValue() == 0.0){
				postageField.getValueField().markError("发往中国的产品邮费不能为零");
				return;
			}
			
			if (packages == null || CollectionUtil.isEmpty(packages)){
				SimpleMessageBox.error("错误", "发往中国的库存必须输入物流信息，请点击绿色加号增加物流包裹信息", CompleteCallback.Nil);
				return;
			}
			
			for (PackageRow row : packages) {
				if (row.validate() == Boolean.FALSE){
					return;
				}
			}
		}
		
		if (currencyRateField.getDouble() == null || currencyRateField.getDouble() == 0.0) {
			currencyRateField.markError("请输入当前实时汇率信息");
			return;
		}
		
		SimpleMessageBox.confirm("确认", "您确定要创建这条购买记录吗？", new DataCallback<Boolean>() {
			@Override
			public void onCompleted(Boolean data) {
				if (data == Boolean.TRUE) {
					createPurchaseRecord();
				}
			}
		});
	}
	
	private List<PackageItem> getPackageItems(){
		return Linq.select(packages, new Func1<PackageRow, PackageItem>(){
			   @Override
			   public PackageItem run(PackageRow param) {
				  return param.getItem();
			   }
		});
	}
	
	private void createPurchaseRecord() {
		final String passport = SessionManager.getPassport();
		
		CreatePurchaseRecordRequest request = new CreatePurchaseRecordRequest();
		request.setCost(costField.getValue());
		request.setPostage(postageField.getValue());
		request.setCostCurrency(costField.getCurrencyField().getSelectedOption().getName());
		request.setPostageCurrency(postageField.getCurrencyField().getSelectedOption().getName());
		request.setLocation(locationField.getSelectedOption().getLocation());
		request.setCount(countField.getInteger());
		request.setBuyerId(buyerField.getSelectedOption().getUserId());
		request.setPosterId(posterField.getSelectedOption().getUserId());
		request.setCurrencyRate(currencyRateField.getDouble());
		request.setDatePurchased(datePurchasedField.getDate());
		request.setProductId(purchaseRecordItem.getProductId());
		
		SimpleModal.show("创建新购买记录...");
		Services.ProductService.CreatePurchaseRecord(passport, request, new AsyncCallback<String>(){
			@Override
			public void onFailure(Throwable caught) {
				SimpleModal.hide();
				ErrorHandler.handleServiceError(caught);
			}
			
			@Override
			public void onSuccess(String result) {
				SimpleModal.hide();
				
				List<PackageItem> packages = getPackageItems();
				if (Util.isNullOrEmpty(result) || CollectionUtil.isEmpty(packages)){
					if (action != null){
						action.run();
					}
					return;
				}
				
				for (PackageItem packageItem : packages) {
					 packageItem.setReference(result);
					 packageItem.setShippingAddress(locationField.getSelectedOption().getCname());
					 packageItem.setType(PackageType.Stock.getType());
					 packageItem.setDescription(purchaseRecordItem.getProductName());
				}
				
				AddPackageRequest request = new AddPackageRequest();
				request.setPackageItems(packages);
				
				SimpleModal.show("创建物流包裹...");
				Services.PackageService.AddPackage(passport, request, new AsyncCallback<Boolean>() {
					@Override
					public void onFailure(Throwable caught) {
						SimpleModal.hide();
						ErrorHandler.handleServiceError(caught);
					}
					
					@Override
					public void onSuccess(Boolean result) {
						SimpleModal.hide();
						if (action != null){
							action.run();
						}
					}
				});
			}
		});
	}
	
}
